package com.nuc.seckill.utils;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;

/**
 * 分布式限流工具类
 *
 * @author 石一歌
 * @date 2022-08-13 21:07
 */
@Component
public class DistrubuteLimitUtil {

    private static final String LIMIT = "local times = redis.call('incr', KEYS[1])\n" +
            "if times == 1 then\n" +
            "    redis.call('expire', KEYS[1], ARGV[1])\n" +
            "end\n" +
            "if times > tonumber(ARGV[2]) then\n" +
            "    return 0\n" +
            "end\n" +
            "return 1";
    private DefaultRedisScript<Long> getRedisScript;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 执行脚本
     *
     * @return boolean
     * @author 石一歌
     * @date 2022/8/13 22:01
     */
    public boolean exec() throws IOException {
        ArrayList<String> keyList = new ArrayList<>();
        String key = "ip:" + System.currentTimeMillis();
        keyList.add(key);
        return redisTemplate.execute(getRedisScript, keyList, 3000, 6) == 1;
    }

    /**
     * 初始化
     *
     * @author 石一歌
     * @date 2022/8/13 22:01
     */
    @PostConstruct
    public void init() {
        getRedisScript = new DefaultRedisScript<>();
        getRedisScript.setResultType(Long.class);
        getRedisScript.setScriptText(LIMIT);
    }

}
